/**
 *
 */
package com.trhui.mallbook.domain.common;

import com.alibaba.fastjson.annotation.JSONField;
import com.trhui.mallbook.common.rsa.RsaUtil;
import com.trhui.mallbook.common.utils.JsonUtil;
import com.trhui.mallbook.common.utils.StringUtil;
import com.trhui.mallbook.enums.ChannelTypeEnum;
import com.trhui.mallbook.enums.ServerCodeEnum;

import java.io.Serializable;
import java.util.Map;

/**
 * 接口请求包
 *
 * @author linqy
 */
public class ApiRequest implements Serializable {
    private static final long serialVersionUID = -8130938432046696213L;

    /**
     * 请求订单号
     */
    @JSONField(serialize = false)
    private String merOrderId;

    /**
     * 商户号
     */
    @JSONField(serialize = false)
    private String merchantNo;

    /**
     * 签名，由merchantNo+date+params通过MD5加密
     */
    private String sign;

    /**
     * 业务类型编号
     */
    @JSONField(serialize = false)
    private String serverCode;

    /**
     * 业务参数，json格式
     */
    @JSONField(serialize = false)
    private String params;

    /**
     * 时间戳
     */
    @JSONField(serialize = false)
    private String date;

    /**
     * 接口版本号，不同版本号触发不同接口业务
     */
    @JSONField(serialize = false)
    private String version;

    @JSONField(serialize = false)
    private String channelType;

    private Map<String, Object> extraParams;

    public Map<String, Object> getExtraParams() {
        return extraParams;
    }

    public void setExtraParams(Map<String, Object> extraParams) {
        this.extraParams = extraParams;
    }

    public String getMerOrderId() {
        return merOrderId;
    }

    public void setMerOrderId(String merOrderId) {
        this.merOrderId = merOrderId;
    }

    public String getMerchantNo() {
        return merchantNo;
    }

    public void setMerchantNo(String merchantNo) {
        this.merchantNo = merchantNo;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getServerCode() {
        return serverCode;
    }

    public void setServerCode(String serverCode) {
        this.serverCode = serverCode;
    }

    public String getParams() {
        return params;
    }

    public void setParams(String params) {
        this.params = params;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getChannelType() {
        return channelType;
    }

    public void setChannelType(String channelType) {
        this.channelType = channelType;
    }

    @Override
    public String toString() {
        // 订单号 + 商户号 +渠道类型＋ 时间戳 + 业务参数json
        StringBuffer sb = new StringBuffer();
        sb.append(StringUtil.convertNull(merOrderId))
                .append(StringUtil.convertNull(merchantNo))
                .append(StringUtil.convertNull(channelType))
                .append(StringUtil.convertNull(date))
                .append(StringUtil.convertNull(params));
        return sb.toString();
    }

    private ApiRequest(ApiRequestBuild apiRequestBuild) {
        this.merOrderId = apiRequestBuild.merOrderId;
        this.merchantNo = apiRequestBuild.merchantNo;
        this.serverCode = apiRequestBuild.serverCode;
        this.params = apiRequestBuild.params;
        this.date = apiRequestBuild.date;
        this.version = apiRequestBuild.version;
        this.channelType = apiRequestBuild.channelType;
        this.extraParams = apiRequestBuild.extraParams;
    }

    private ApiRequest(ApiRequestBuild apiRequestBuild, String merchantPrivateKey) {
        this.merOrderId = apiRequestBuild.merOrderId;
        this.merchantNo = apiRequestBuild.merchantNo;
        this.serverCode = apiRequestBuild.serverCode;
        this.params = apiRequestBuild.params;
        this.date = apiRequestBuild.date;
        this.version = apiRequestBuild.version;
        this.channelType = apiRequestBuild.channelType;
        this.extraParams = apiRequestBuild.extraParams;

        if (StringUtil.isNotBlank(merchantPrivateKey)) {
            this.sign = RsaUtil.sign(toString(), merchantPrivateKey);
        }
    }

    public static class ApiRequestBuild {
        private String merOrderId;
        private String merchantNo;
        private String sign;
        private String serverCode;
        private String params;
        private String date;
        private String version;
        private String channelType;
        private Map<String, Object> extraParams;

        public ApiRequestBuild extraParams(Map<String, Object> extraParams) {
            this.extraParams = extraParams;
            return this;
        }

        public ApiRequestBuild merOrderId(String merOrderId) {
            this.merOrderId = merOrderId;
            return this;
        }

        public ApiRequestBuild merchantNo(String merchantNo) {
            this.merchantNo = merchantNo;
            return this;
        }

        public ApiRequestBuild serverCode(ServerCodeEnum serverCode) {
            this.serverCode = serverCode.getCode();
            return this;
        }

        public ApiRequestBuild params(BaseRequest bizParams) {
            this.params = JsonUtil.toJsonStr(bizParams);
            // 额外参数
            if (bizParams != null) {
                this.extraParams = bizParams.getExtraParams();
            }
            return this;
        }

        public ApiRequestBuild date(String date) {
            this.date = date;
            return this;
        }

        public ApiRequestBuild version(String version) {
            this.version = version;
            return this;
        }

        public ApiRequestBuild channelType(ChannelTypeEnum channelType) {
            this.channelType = channelType.getCode();
            return this;
        }

        public ApiRequestBuild sign(String sign) {
            this.sign = sign;
            return this;
        }

        public ApiRequest build() {
            return new ApiRequest(this);
        }

        public ApiRequest build(String merchantPrivateKey) {
            return new ApiRequest(this, merchantPrivateKey);
        }
    }

}
